/****************************************************************************
    Kantaoke, a karaoke game made with BennuGD.
    Copyright (C) 2010 Joseba García Echebarria

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/

/****************************************************************************
    See the following webpage for more info:
http://ultrastardeluxe.xtremeweb-hosting.net/wiki/doku.php?id=editor:txt_file

note[120] =
    "C 0", "C#0", "D 0", "D#0", "E 0", "F 0", "F#0", "G 0", "G#0", "A 0", "A#0", "B 0",  
    "C 1", "C#1", "D 1", "D#1", "E 1", "F 1", "F#1", "G 1", "G#1", "A 1", "A#1", "B 1",  
    "C 2", "C#2", "D 2", "D#2", "E 2", "F 2", "F#2", "G 2", "G#2", "A 2", "A#2", "B 2",  
    "C 3", "C#3", "D 3", "D#3", "E 3", "F 3", "F#3", "G 3", "G#3", "A 3", "A#3", "B 3",  
    "C 4", "C#4", "D 4", "D#4", "E 4", "F 4", "F#4", "G 4", "G#4", "A 4", "A#4", "B 4",  
    "C 5", "C#5", "D 5", "D#5", "E 5", "F 5", "F#5", "G 5", "G#5", "A 5", "A#5", "B 5",  
    "C 6", "C#6", "D 6", "D#6", "E 6", "F 6", "F#6", "G 6", "G#6", "A 6", "A#6", "B 6",  
    "C 7", "C#7", "D 7", "D#7", "E 7", "F 7", "F#7", "G 7", "G#7", "A 7", "A#7", "B 7",  
    "C 8", "C#8", "D 8", "D#8", "E 8", "F 8", "F#8", "G 8", "G#8", "A 8", "A#8", "B 8",  
    "C 9", "C#9", "D 9", "D#9", "E 9", "F 9", "F#9", "G 9", "G#9", "A 9", "A#9", "B 9"

notefreq[120] =
16.35, 17.32, 18.35, 19.45, 20.60, 21.83, 23.12, 24.50, 25.96, 27.50, 29.14, 30.87,
32.70, 34.65, 36.71, 38.89, 41.20, 43.65, 46.25, 49.00, 51.91, 55.00, 58.27, 61.74,
65.41, 69.30, 73.42, 77.78, 82.41, 87.31, 92.50, 98.00, 103.83, 110.00, 116.54, 123.47f, 
130.81, 138.59, 146.83, 155.56, 164.81, 174.61, 185.00, 196.00, 207.65, 220.00, 233.08, 246.94,
261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.30, 440.00, 466.16, 493.88,
523.25, 554.37, 587.33, 622.25, 659.26, 698.46, 739.99, 783.99, 830.61, 880.00, 932.33, 987.77, 
1046.50, 1108.73, 1174.66, 1244.51, 1318.51, 1396.91, 1479.98, 1567.98, 1661.22, 1760.00,  1864.66, 1975.53, 
2093.00, 2217.46, 2349.32, 2489.02, 2637.02, 2793.83, 2959.96, 3135.96, 3322.44, 3520.00, 3729.31, 3951.07, 
4186.01, 4434.92, 4698.64, 4978.03, 5274.04, 5587.65, 5919.91, 6271.92, 6644.87, 7040.00, 7458.62,  7902.13, 
8372.01, 8869.84, 9397.27, 9956.06, 10548.08, 11175.30, 11839.82, 12543.85, 13289.75, 14080.00, 14917.24, 15804.26

The notes appear to be:
'C2', 'C#2', 'D2', 'D#2', 'E2', 'F2', 'F#2', 'G2', 'G#2', 'A2', 'A#2', 'B2'
65.41, 69.30, 73.42, 77.78, 82.41, 87.31, 92.50, 98.00, 103.83, 110.00, 116.54, 123.47f

****************************************************************************/

#ifndef __LYRICS_INC__
#define __LYRICS_INC__

// Read the header for the description info. Leave the file descriptor
// pointer where the lyrics start.
// Some info taken from: 
// http://ultrastardeluxe.xtremeweb-hosting.net/wiki/doku.php?id=editor:txt_file
Function parse_file(string filename, song pointer kar)
Private
  int pos=0, n=0, retval=0;
  string line;

Begin
  // Open the description file
  // Try to handle the case where the filename and the FS encoding don't match
  if(! fexists(filename))
    filename = iconv("UTF8//TRANSLIT", kar.charset, filename);
    if(! file_exists(filename))
      filename = "";
    end;
  end;

  kar.fd = fopen(filename, O_READ);
  if(!kar.fd)
    dbg_print("descriptor file '"+filename+"' couldn't be opened");
    return -1;
  End;

  // Determine the charset of the file (in case of failure, will default to a
  // wrong value most of the times)
  kar.charset = determine_charset(filename);

  //Read the file, and fill the kar struct
  while(!feof(kar.fd) && line[0] != ":")
    line = fgets(kar.fd);
    if((pos = find(line, "#MP3:")) != -1)
      kar.music_file = substr(line, pos+len("#MP3:"));
    #ifndef NO_SMPEG
      elif((pos = find(line, "#VIDEO:")) != -1)
        kar.video_file = substr(line, pos+len("#VIDEO:"));
    #endif
    elif((pos = find(line, "#TITLE:")) != -1)
      kar.title = substr(line, pos+len("#TITLE:"));
    elif((pos = find(line, "#ARTIST:")) != -1)
      kar.artist = substr(line, pos+len("#ARTIST:"));
    elif((pos = find(line, "#COVER:")) != -1)
      kar.coverpath = substr(line, pos+len("#COVER:"));
    elif((pos = find(line, "#BACKGROUND:")) != -1)
      kar.bgpath = substr(line, pos+len("#BACKGROUND:"));
    elif((pos = find(line, "#GAP:")) != -1)
      kar.gap = atoi(substr(line, pos+len("#GAP:")))/10;
    #ifndef NO_SMPEG
      elif((pos = find(line, "#VIDEOGAP:")) != -1)
        kar.videogap = atoi(substr(line, pos+len("#VIDEOGAP:")))/10;
    #endif
    elif((pos = find(line, "#BPM:")) != -1)
      kar.bpm = atoi(substr(line, pos+len("#BPM:")));
    elif((pos = find(line, "#RELATIVE:")) != -1)
      kar.relative = substr(line, pos+len("#RELATIVE:"));
    elif((pos = find(line, "#LICENSE:")) != -1)
      kar.license = substr(line, pos+len("#LICENSE:"));
    elif((pos = find(line, "#URL:")) != -1)
      kar.artist = substr(line, pos+len("#URL:"));
    end;
    n++;
  end;

  // We've read one line that includes lyrics (to be able to detect the start
  // of the lyrics). Thus, we have to reduce n.
  n--;

  //TODO: Review
  if(kar.gap != 0 && kar.videogap != 0)
    kar.videogap += kar.gap;
  end;

  kar.artist = iconv(NATIVE_CHARSET, kar.charset, kar.artist);
  kar.title  = iconv(NATIVE_CHARSET, kar.charset, kar.title );
  
  // If some of the files don't exist, try to convert the paths to UFT8,
  // as most modern FS's use it
  if(! file_exists(kar.coverpath))
    kar.coverpath=iconv("UTF8//TRANSLIT", kar.charset, kar.coverpath);
  end;
  
  if(! file_exists(kar.bgpath))
    kar.bgpath=iconv("UTF8//TRANSLIT", kar.charset, kar.bgpath);
  end;
  
  if(! file_exists(kar.music_file))
    kar.music_file=iconv("UTF8//TRANSLIT", kar.charset, kar.music_file);
  end;

  //Set the read buffer at the beginning of the lyrics, don't close the file
  //descriptor
  fseek(kar.fd, 0, SEEK_SET);
  for(n; n>0; n--)
    fgets(kar.fd);
  end;  
End;

//Reads a whole file and fills all the data associated to it
Function int ReadBeatFile(song pointer kar)
Private
  int retval=0, i=0, j=0, deact_time=0;

Begin
  //Read the song lyrics
  while(retval != -2 && i < lineslimit )
    while(retval != -1 && j < syllableslimit )
      retval = ReadBeat(kar.bpm, kar.fd,
                &kar.lines[i].syllables[j].activation_time,
                &kar.lines[i].syllables[j].deactivation_time,
                &kar.lines[i].syllables[j].tone,
                kar.gap, kar.videogap,
                &kar.lines[i].syllables[j].text);
      kar.lines[i].syllables[j].text = iconv (NATIVE_CHARSET, kar.charset,
                kar.lines[i].syllables[j].text);
      //This way, we also fill the line text
      kar.lines[i].line_text += kar.lines[i].syllables[j].text;
        
      //Deact_time holds the maximum deactivation time in a verse
      if(deact_time < kar.lines[i].syllables[j].deactivation_time)
        deact_time = kar.lines[i].syllables[j].deactivation_time;
      end;
      j++;
    end;

    kar.lines[i].activation_time = kar.lines[i].syllables[0].activation_time;
    kar.lines[i].deactivation_time = deact_time;
    if(i >= 1)
      kar.lines[i].appearance_time = kar.lines[i-1].activation_time;
    else
      //You've got a 3 seconds lapse between the first line appears and the
      //song starts
      kar.lines[0].appearance_time = kar.lines[0].activation_time - 300;
    end;
    retval=0; j=0; i++;
  end
End;

//Reads the data for a "beat", usually just a syllable
Function int ReadBeat(int bpm, int fd, int pointer time,
            int pointer deact_time, int pointer tone, int gap, int videogap,
            string pointer lyrics)
Private
  int pos=0, t_in_beats=0;
  string line="";

Begin
  if(!fd || desc_file_finished == 1)
    return -2;
  end;

  line = fgets(fd);
  //Look for the file finish descriptor or for the last line in the file
  if(line[0] == "E" || feof(fd))
    desc_file_finished = 1;
    return -2;
  end;

  if(line[0] == "-" || len(line) == 0)
    *time = atoi(_trim(line))*10;
    return -1;
  end;

  pos = find(line, " ");
  line = substr(line, pos+1);
  pos = find(line, " ");
  //What we get is a beat, not an absolut time, gotta convert it
  t_in_beats = atoi(substr(line, 0, pos));
  *time = beat_2_csec(t_in_beats, bpm) + gap + videogap;
  line = substr(line, pos+1);
  pos = find(line, " ");
  t_in_beats += atoi(substr(line, 0, pos));
  *deact_time = beat_2_csec(t_in_beats, bpm) + gap + videogap;
  line = substr(line, pos+1);
  pos = find(line, " ");
  *tone = atoi(substr(line, 0, pos));
  line = substr(line, pos+1);
  *lyrics = substr(line, 0, len(line));
  
  return 0;
end;

#endif
